home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / dpmigcc5.zip / RSX / SOURCE / FPU-EMU / LOAD_STO.C < prev    next >
C/C++ Source or Header  |  1994-05-27  |  7KB  |  238 lines

  1. /*---------------------------------------------------------------------------+
  2.  |  load_store.c                                                             |
  3.  |                                                                           |
  4.  | This file contains most of the code to interpret the FPU instructions     |
  5.  | which load and store from user memory.                                    |
  6.  |                                                                           |
  7.  | Copyright (C) 1992,1993,1994                                              |
  8.  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
  9.  |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
  10.  |                                                                           |
  11.  |                                                                           |
  12.  +---------------------------------------------------------------------------*/
  13.  
  14. /*---------------------------------------------------------------------------+
  15.  | Note:                                                                     |
  16.  |    The file contains code which accesses user memory.                     |
  17.  |    Emulator static data may change when user memory is accessed, due to   |
  18.  |    other processes using the emulator while swapping is in progress.      |
  19.  +---------------------------------------------------------------------------*/
  20.  
  21. #include <asm/segment.h>
  22.  
  23. #include "fpu_system.h"
  24. #include "exception.h"
  25. #include "fpu_emu.h"
  26. #include "status_w.h"
  27. #include "control_w.h"
  28.  
  29.  
  30. #define _NONE_ 0   /* FPU_st0_ptr etc not needed */
  31. #define _REG0_ 1   /* Will be storing st(0) */
  32. #define _PUSH_ 3   /* Need to check for space to push onto stack */
  33. #define _null_ 4   /* Function illegal or not implemented */
  34.  
  35. #define pop_0()    { pop_ptr->tag = TW_Empty; top++; }
  36.  
  37.  
  38. static unsigned char const type_table[32] = {
  39.   _PUSH_, _PUSH_, _PUSH_, _PUSH_,
  40.   _null_, _null_, _null_, _null_,
  41.   _REG0_, _REG0_, _REG0_, _REG0_,
  42.   _REG0_, _REG0_, _REG0_, _REG0_,
  43.   _NONE_, _null_, _NONE_, _PUSH_,
  44.   _NONE_, _PUSH_, _null_, _PUSH_,
  45.   _NONE_, _null_, _NONE_, _REG0_,
  46.   _NONE_, _REG0_, _NONE_, _REG0_
  47.   };
  48.  
  49. void load_store_instr(char type, fpu_addr_modes addr_modes)
  50. {
  51.   FPU_REG *pop_ptr;  /* We need a version of FPU_st0_ptr which won't
  52.             change if the emulator is re-entered. */
  53.  
  54.   pop_ptr = NULL;    /* Initialized just to stop compiler warnings. */
  55.   switch ( type_table[(int) (unsigned) type] )
  56.     {
  57.     case _NONE_:
  58.       break;
  59.     case _REG0_:
  60.       pop_ptr = &st(0);       /* Some of these instructions pop after
  61.                  storing */
  62.  
  63.       FPU_st0_ptr = pop_ptr;      /* Set the global variables. */
  64.       FPU_st0_tag = FPU_st0_ptr->tag;
  65.       break;
  66.     case _PUSH_:
  67.       {
  68.     pop_ptr = &st(-1);
  69.     if ( pop_ptr->tag != TW_Empty )
  70.       { stack_overflow(); return; }
  71.     top--;
  72.       }
  73.       break;
  74.     case _null_:
  75.       FPU_illegal();
  76.       return;
  77. #ifdef PARANOID
  78.     default:
  79.       EXCEPTION(EX_INTERNAL);
  80.       return;
  81. #endif PARANOID
  82.     }
  83.  
  84. switch ( type )
  85.   {
  86.   case 000:       /* fld m32real */
  87.     clear_C1();
  88.     reg_load_single();
  89.     if ( (FPU_loaded_data.tag == TW_NaN) &&
  90.     real_2op_NaN(&FPU_loaded_data, &FPU_loaded_data, &FPU_loaded_data) )
  91.       {
  92.     top++;
  93.     break;
  94.       }
  95.     reg_move(&FPU_loaded_data, pop_ptr);
  96.     break;
  97.   case 001:      /* fild m32int */
  98.     clear_C1();
  99.     reg_load_int32();
  100.     reg_move(&FPU_loaded_data, pop_ptr);
  101.     break;
  102.   case 002:      /* fld m64real */
  103.     clear_C1();
  104.     reg_load_double();
  105.     if ( (FPU_loaded_data.tag == TW_NaN) &&
  106.     real_2op_NaN(&FPU_loaded_data, &FPU_loaded_data, &FPU_loaded_data) )
  107.       {
  108.     top++;
  109.     break;
  110.       }
  111.     reg_move(&FPU_loaded_data, pop_ptr);
  112.     break;
  113.   case 003:      /* fild m16int */
  114.     clear_C1();
  115.     reg_load_int16();
  116.     reg_move(&FPU_loaded_data, pop_ptr);
  117.     break;
  118.   case 010:      /* fst m32real */
  119.     clear_C1();
  120.     reg_store_single();
  121.     break;
  122.   case 011:      /* fist m32int */
  123.     clear_C1();
  124.     reg_store_int32();
  125.     break;
  126.   case 012:     /* fst m64real */
  127.     clear_C1();
  128.     reg_store_double();
  129.     break;
  130.   case 013:     /* fist m16int */
  131.     clear_C1();
  132.     reg_store_int16();
  133.     break;
  134.   case 014:     /* fstp m32real */
  135.     clear_C1();
  136.     if ( reg_store_single() )
  137.       pop_0();  /* pop only if the number was actually stored
  138.          (see the 80486 manual p16-28) */
  139.     break;
  140.   case 015:     /* fistp m32int */
  141.     clear_C1();
  142.     if ( reg_store_int32() )
  143.       pop_0();  /* pop only if the number was actually stored
  144.          (see the 80486 manual p16-28) */
  145.     break;
  146.   case 016:     /* fstp m64real */
  147.     clear_C1();
  148.     if ( reg_store_double() )
  149.       pop_0();  /* pop only if the number was actually stored
  150.          (see the 80486 manual p16-28) */
  151.     break;
  152.   case 017:     /* fistp m16int */
  153.     clear_C1();
  154.     if ( reg_store_int16() )
  155.       pop_0();  /* pop only if the number was actually stored
  156.          (see the 80486 manual p16-28) */
  157.     break;
  158.   case 020:     /* fldenv  m14/28byte */
  159.     fldenv(addr_modes);
  160.     break;
  161.   case 022:     /* frstor m94/108byte */
  162.     frstor(addr_modes);
  163.     break;
  164.   case 023:     /* fbld m80dec */
  165.     clear_C1();
  166.     reg_load_bcd();
  167.     reg_move(&FPU_loaded_data, pop_ptr);
  168.     break;
  169.   case 024:     /* fldcw */
  170.     RE_ENTRANT_CHECK_OFF;
  171.     FPU_verify_area(VERIFY_READ, FPU_data_address, 2);
  172.     control_word = get_fs_word((unsigned short *) FPU_data_address);
  173.     RE_ENTRANT_CHECK_ON;
  174.     if ( partial_status & ~control_word & CW_Exceptions )
  175.       partial_status |= (SW_Summary | SW_Backward);
  176.     else
  177.       partial_status &= ~(SW_Summary | SW_Backward);
  178. #ifdef PECULIAR_486
  179.     control_word |= 0x40;  /* An 80486 appears to always set this bit */
  180. #endif PECULIAR_486
  181.     NO_NET_DATA_EFFECT;
  182.     NO_NET_INSTR_EFFECT;
  183.     break;
  184.   case 025:      /* fld m80real */
  185.     clear_C1();
  186.     reg_load_extended();
  187.     reg_move(&FPU_loaded_data, pop_ptr);
  188.     break;
  189.   case 027:      /* fild m64int */
  190.     clear_C1();
  191.     reg_load_int64();
  192.     reg_move(&FPU_loaded_data, pop_ptr);
  193.     break;
  194.   case 030:     /* fstenv  m14/28byte */
  195.     fstenv(addr_modes);
  196.     NO_NET_DATA_EFFECT;
  197.     break;
  198.   case 032:      /* fsave */
  199.     fsave(addr_modes);
  200.     NO_NET_DATA_EFFECT;
  201.     break;
  202.   case 033:      /* fbstp m80dec */
  203.     clear_C1();
  204.     if ( reg_store_bcd() )
  205.       pop_0();  /* pop only if the number was actually stored
  206.          (see the 80486 manual p16-28) */
  207.     break;
  208.   case 034:      /* fstcw m16int */
  209.     RE_ENTRANT_CHECK_OFF;
  210.     FPU_verify_area(VERIFY_WRITE,FPU_data_address,2);
  211.     put_fs_word(control_word, (short *) FPU_data_address);
  212.     RE_ENTRANT_CHECK_ON;
  213.     NO_NET_DATA_EFFECT;
  214.     NO_NET_INSTR_EFFECT;
  215.     break;
  216.   case 035:      /* fstp m80real */
  217.     clear_C1();
  218.     if ( reg_store_extended() )
  219.       pop_0();  /* pop only if the number was actually stored
  220.          (see the 80486 manual p16-28) */
  221.     break;
  222.   case 036:      /* fstsw m2byte */
  223.     RE_ENTRANT_CHECK_OFF;
  224.     FPU_verify_area(VERIFY_WRITE,FPU_data_address,2);
  225.     put_fs_word(status_word(),(short *) FPU_data_address);
  226.     RE_ENTRANT_CHECK_ON;
  227.     NO_NET_DATA_EFFECT;
  228.     NO_NET_INSTR_EFFECT;
  229.     break;
  230.   case 037:      /* fistp m64int */
  231.     clear_C1();
  232.     if ( reg_store_int64() )
  233.       pop_0();  /* pop only if the number was actually stored
  234.          (see the 80486 manual p16-28) */
  235.     break;
  236.   }
  237. }
  238.